package dh01.ex02;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;


public class RandomFileTest {
	
	public static void main(String[] args) {
		Employee[] staff = new Employee[3];
		staff[0] = new Employee("Carl Cracker", 75000, 1987, 12, 15);
		staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1);
		staff[2] = new Employee("Tony Tester", 40000, 1990, 3, 15);

		DataOutputStream out;
		try {
			out = new DataOutputStream(new FileOutputStream("employee.dat"));
			for (Employee e : staff) {
				e.writeData(out);
			}
			out.close();
			
			RandomAccessFile in = new RandomAccessFile("employee.dat", "r");
			int size = (int) in.length() / Employee.RECORD_SIZE;
			Employee[] newEmployee = new Employee[size];
			for (int i = size - 1; i >= 0; i--) {
				newEmployee[i] = new Employee();
				in.seek(i * Employee.RECORD_SIZE);
				newEmployee[i].readData(in);
			}
			in.close();
			
			for (Employee e : newEmployee) {
				System.out.println(e);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}


class Employee {
	public Employee() {
		
	}
	
	public Employee(String n, double s, int year, int month, int day) {
		name = n;
		salary = s;
		GregorianCalendar calendar = new GregorianCalendar(year, month - 1, day);
		hireDay = calendar.getTime();
	}
	
	public String getName() {
		return name;
	}

	public double getSalary() {
		return salary;
	}

	public Date getHireDay() {
		return hireDay;
	}
	
	public void raiseSalary(double byPercent) {
		double raise = salary / 100 * byPercent;
		salary += raise;
	}

	@Override
	public String toString() {
		return getClass().getName() + "[name=" + name +", salary=" + salary + ", hireDay=" + hireDay + "]";
	}
	
	public void writeData(DataOutput out) throws IOException {
		DataIO.writeFixedString(name, NAME_SIZE, out);
		// notice when write double or int, don't need specify fixed length.
		out.writeDouble(salary);
		GregorianCalendar calendar = new GregorianCalendar();
		calendar.setTime(hireDay);
		out.writeInt(calendar.get(Calendar.YEAR));
		out.writeInt(calendar.get(Calendar.MONTH) + 1);
		out.writeInt(calendar.get(Calendar.DAY_OF_MONTH));
	}
	
	public void readData(DataInput in) throws IOException {
		name = DataIO.readFixedString(NAME_SIZE, in);
		salary = in.readDouble();
		int y = in.readInt();
		int m = in.readInt();
		int d = in.readInt();
		GregorianCalendar calendar = new GregorianCalendar(y, m - 1, d);
		hireDay = calendar.getTime();
	}
	
	public static final int NAME_SIZE = 40;
	public static final int RECORD_SIZE = 2 * NAME_SIZE + 8 + 3 * 4;
	
	private String name;
	private double salary;
	private Date hireDay;
}

class DataIO {
	public static String readFixedString(int size, DataInput in) throws IOException {
		StringBuilder b = new StringBuilder(size);
		int i = 0;
		boolean more = true;
		while (more && i < size) {
			// notice use readChar(), not readInt() or etc.
			char ch = in.readChar();
			i++;
			if (ch == 0) {
				more = false;
			} else {
				b.append(ch);
			}
		}
		// Why need to skip?
		// Because in will need to continue reading other content
		in.skipBytes(2 * (size - 1));
		return b.toString();
	}
	
	/**
	 * @param s 
	 * @param size if s.length > size, omit other;
	 * @param out
	 * @throws IOException 
	 */
	public static void writeFixedString(String s, int size, DataOutput out) throws IOException {
		for (int i = 0; i < size; i++) {
			char ch = 0;
			if (i < s.length()) {
				ch = s.charAt(i);
			}
			// TODO Why parameter type is int?
			// notice should use writeChar(), not write();
			out.writeChar(ch);
		}
	}
}